<?php

require_once ('Joob/Controller/Abstract.php');

/**
 * The main and frontier controller
 * @author griever
 */
class Joob_Controller_Dispatcher {
	
	protected $registry;
	
	protected $requestParser;
	
	protected $dispatched = false;
	
	public function __construct() {
		require_once 'Joob/Registry/KVP.php';
		$this->registry = Joob_Registry_KVP::getInstance ();
		$this->requestParser = $this->registry->get ( 'parser', 'Joob:http:request' );
	}
	
	/**
	 * Dispatch the request, append the response body if any
	 * @param unknown_type $request the request object
	 * @param unknown_type $response the response object
	 * @throws Joob_Exceptions_NotFound
	 * @throws Exception
	 */
	public function dispatch($request, $response) {
		$this->dispatched = true;
		$request = $this->requestParser->parseRequest ( $request );
		
		require_once ('Joob/Controller/Router/Standard.php');
		$router = new Joob_Controller_Router_Standard ();
		$module = $router->route ( $request );
		
		if ($module == null) {
			require_once ('Joob/Exceptions/NotFound.php');
			throw new Joob_Exceptions_NotFound ( "Component or module not found" );
		}
		
		$module->setRequest ( $request );
		
		//Start output buffering
		$obLevel = ob_get_level();
		ob_start ();
		
		try {
			//FIXME: Why does Zend Fw call init() method in the module's (controller's) constructor
			$module->init ();
			$taskFunction = $this->getTaskFunction($request);
			$module->dispatch ($taskFunction);
			$module->destroy ();
		} catch ( Exception $e ) {
			// Clean output buffer on error
			$curObLevel = ob_get_level();
			if ($curObLevel > $obLevel)	{
				do {
					ob_get_clean();
					$curObLevel = ob_get_level();
				} while ($curObLevel > $obLevel);
			}
			throw $e;
		}
		
		//retrieve the output buffer and clean it
		$content = ob_get_clean();
		$response->appendBody($content);
		
		$module = null;
	}
	
	public function destroy() {
		$this->registry = null;
		$this->requestParser = null;
		$this->request = null;
	}
	
	/**
	 * Get the appropriate task function of the request
	 * @param unknown_type $request
	 */
	public function getTaskFunction($request)	{
		$task = $request->getTaskName ();
		return $this->formatTaskName($task)."Task"; 
	}
	
	protected function formatTaskName($task)	{
		$formatted = str_replace("-", " ", $task);
		$formatted = ucwords($formatted);
		$formatted = str_replace(" ", "", $formatted);
		return strtolower(substr($formatted, 0, 1)).substr($formatted, 1);
	}
}

?>